{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "d1f20875-c50d-46df-906b-49ec1d0c6002",
   "metadata": {},
   "source": [
    "## 10.7 使用卷积神经网络训练CIFAR-10数据集\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c90a18b9-d8e8-431c-856c-35f1e4ed05e1",
   "metadata": {},
   "source": [
    "### 1.任务描述\n",
    "\n",
    "使用卷积神经网络训练CIFAR-10数据集。\n",
    "\n",
    "要求：\n",
    "\n",
    "- 加载CIFAR-10数据集，并进行预处理\n",
    "- 使用Model类搭建神经网络，结构要求如下\n",
    "    - 层1：卷积层（卷积核大小：5×5；输出通道数：6；使用全0填充）\n",
    "    - 层2：批标准化。\n",
    "    - 层3：激活（ReLU函数）\n",
    "    - 层4：池化（池化核大小：2×2；步长：2；使用全0填充）\n",
    "    - 层5：舍弃（舍弃率：0.2）\n",
    "    - 层6：拉平\n",
    "    - 层7：全连接层/隐含层（神经元个数：128；激活函数：ReLU）\n",
    "    - 层8：舍弃（舍弃率：0.2）\n",
    "    - 层9：全连接层/输出层（神经元个数：10；激活函数：Softmax）\n",
    "- 优化器：Adam\n",
    "- 损失函数：交叉熵损失函数\n",
    "- 训练轮数：5\n",
    "- 批大小：32\n",
    "- 进行训练，并打印训练过程\n",
    "- 对损失和准确率进行可视化"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "f5b4fc39-cbcf-432a-bf1e-e75e642d4b87",
   "metadata": {},
   "source": [
    "### 2.知识准备\n",
    "\n",
    "见教程。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "55043130-4496-43a3-803b-9bc1cea8b1b8",
   "metadata": {},
   "source": [
    "### 3.任务分析\n",
    "\n",
    "定义一个Baseline的网络实现类，并继承Model类，在该类的初始化函数中，通过Conv2D、BatchNormalization、Activation、MaxPool2D、Dropout、Flatten、Dense等函数来定义表明每层网络结构的成员变量。在Baseline实现类中，还需要定义参数x在网络中传递顺序的前向传播函数，该函数的返回结果为y。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "435c6090-cfda-4f46-a550-22a368e41e4a",
   "metadata": {},
   "source": [
    "### 4.任务实施\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "ec75eb6c-5da3-467d-a471-ca3b47242dd6",
   "metadata": {},
   "source": [
    "执行代码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "2ae9da58-e339-4d22-9f8d-ca255711d89e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/5\n",
      "1563/1563 [==============================] - 12s 4ms/step - loss: 1.6445 - sparse_categorical_accuracy: 0.4028 - val_loss: 1.4258 - val_sparse_categorical_accuracy: 0.4819\n",
      "Epoch 2/5\n",
      "1563/1563 [==============================] - 7s 4ms/step - loss: 1.4143 - sparse_categorical_accuracy: 0.4913 - val_loss: 1.2950 - val_sparse_categorical_accuracy: 0.5349\n",
      "Epoch 3/5\n",
      "1563/1563 [==============================] - 7s 4ms/step - loss: 1.3312 - sparse_categorical_accuracy: 0.5218 - val_loss: 1.2652 - val_sparse_categorical_accuracy: 0.5472\n",
      "Epoch 4/5\n",
      "1563/1563 [==============================] - 7s 4ms/step - loss: 1.2856 - sparse_categorical_accuracy: 0.5399 - val_loss: 1.3579 - val_sparse_categorical_accuracy: 0.5206\n",
      "Epoch 5/5\n",
      "1563/1563 [==============================] - 7s 4ms/step - loss: 1.2466 - sparse_categorical_accuracy: 0.5555 - val_loss: 1.2731 - val_sparse_categorical_accuracy: 0.5532\n",
      "Model: \"baseline\"\n",
      "_________________________________________________________________\n",
      " Layer (type)                Output Shape              Param #   \n",
      "=================================================================\n",
      " conv2d (Conv2D)             multiple                  456       \n",
      "                                                                 \n",
      " batch_normalization (BatchN  multiple                 24        \n",
      " ormalization)                                                   \n",
      "                                                                 \n",
      " activation (Activation)     multiple                  0         \n",
      "                                                                 \n",
      " max_pooling2d (MaxPooling2D  multiple                 0         \n",
      " )                                                               \n",
      "                                                                 \n",
      " dropout (Dropout)           multiple                  0         \n",
      "                                                                 \n",
      " flatten (Flatten)           multiple                  0         \n",
      "                                                                 \n",
      " dense (Dense)               multiple                  196736    \n",
      "                                                                 \n",
      " dropout_1 (Dropout)         multiple                  0         \n",
      "                                                                 \n",
      " dense_1 (Dense)             multiple                  1290      \n",
      "                                                                 \n",
      "=================================================================\n",
      "Total params: 198,506\n",
      "Trainable params: 198,494\n",
      "Non-trainable params: 12\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "# 1，导入模块\n",
    "import tensorflow as tf\n",
    "from tensorflow.keras.layers import Conv2D, BatchNormalization, Activation, MaxPool2D, Dropout, Flatten, Dense\n",
    "from tensorflow.keras import Model\n",
    "from matplotlib import pyplot as plt\n",
    "# 2，加载数据集\n",
    "(x_train, y_train), (x_test, y_test) = tf.keras.datasets.cifar10.load_data()\n",
    "# 归一化\n",
    "x_train, x_test = x_train / 255.0, x_test / 255.0\n",
    "# 3，创建网络\n",
    "class Baseline(Model):\n",
    "    def __init__(self):\n",
    "        super(Baseline,self).__init__()\n",
    "        # 卷积层\n",
    "        self.c1=Conv2D(filters=6,kernel_size=(5,5),padding='same')\n",
    "        # BN层\n",
    "        self.b1 = BatchNormalization() \n",
    "        # 激活层\n",
    "        self.a1 = Activation('relu')\n",
    "        # 池化层\n",
    "        self.p1 = MaxPool2D(pool_size=(2, 2), strides=2, padding='same')  \n",
    "        # Dropout层\n",
    "        self.d1 = Dropout(0.2)        \n",
    "        # 拉平层\n",
    "        self.flatten = Flatten()\n",
    "        # 隐含层\n",
    "        self.f1 = Dense(128, activation='relu')\n",
    "        # Dropout层 \n",
    "        self.d2 = Dropout(0.2)\n",
    "        # 输出层\n",
    "        self.f2 = Dense(10, activation='softmax')\n",
    "    def call(self,x):\n",
    "        # 前向传播\n",
    "        x = self.c1(x)\n",
    "        x = self.b1(x)\n",
    "        x = self.a1(x)\n",
    "        x = self.p1(x)\n",
    "        x = self.d1(x)        \n",
    "        x = self.flatten(x)\n",
    "        x = self.f1(x)\n",
    "        x = self.d2(x)\n",
    "        y = self.f2(x)\n",
    "        return y\n",
    "\n",
    "# 4，配置网络\n",
    "# 实例化模型对象\n",
    "model = Baseline()\n",
    "model.compile(\n",
    "    # 优化器\n",
    "    optimizer='adam',\n",
    "    # 损失函数\n",
    "    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits= False),\n",
    "    # 评测方法\n",
    "    metrics=['sparse_categorical_accuracy']\n",
    ")\n",
    "\n",
    "# 5，训练网络\n",
    "history = model.fit(\n",
    "    x_train, y_train, batch_size=32, epochs=5, \n",
    "    validation_data=(x_test, y_test), validation_freq=1)\n",
    "# 输出模型结构和统计结果\n",
    "model.summary()\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e6044c99-0741-4378-b2b6-f60c293cc3a9",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
